From Vibe Coding to Contract-Driven AI Development
Vibe Coding funktioniert hervorragend - solange das Projekt nicht zu wachsen beginnt. Erfahre, wie sich leistungsstarke KI-Modelle, günstigere Modelle, Verträge und Code-Generatoren zu einem skalierbaren Workflow kombinieren lassen.
Vom Vibe Coding zur Contract-Driven AI Development
Wie man die teuerste Intelligenz für Unsicherheit einsetzt und Wiederholbarkeit in Verträge, Generatoren und günstigere Modelle verlagert.
Stellen wir uns einen scheinbar gewöhnlichen Pivot vor.
Ein Shop, der bisher Standardprodukte verkauft hat, beginnt, digitale Jahreslizenzen anzubieten. Nach erfolgreicher Verbuchung der Zahlung soll der Nutzer automatisch für 365 Tage Zugriff erhalten. Die erneute Verarbeitung desselben Webhooks darf keine zweite Lizenz erzeugen.
Eine solche Anforderung kann man an einen Coding Agent übergeben.
Er liest das Repository. Er findet Checkout, Produkte, Bestellungen und Zahlungen. Er schlägt ein Datenmodell vor. Er fügt eine Migration, einen Service, einige Endpunkte und Tests hinzu. Mit einem guten Modell besteht eine hohe Wahrscheinlichkeit, dass dabei eine funktionierende Lösung entsteht.
Nur ist „Code schreiben“ hier der am wenigsten interessante Teil der Aufgabe.
Zuerst muss entschieden werden, was eine Lizenz in diesem System eigentlich ist.
Ist sie ein eigener Checkout-Typ?
Ein Verhalten des Produkts?
Entsteht das Entitlement direkt im Payment-Callback?
Was passiert nach einem Fehler?
Wie führen wir Retries durch?
Wo garantieren wir Idempotenz?
Soll die Bestellung auf das aktuelle Produkt verweisen oder einen Snapshot dessen speichern, was der Kunde tatsächlich gekauft hat?
Erst die Antworten auf diese Fragen bestimmen, welcher Code sinnvoll ist.
Und genau hier sehe ich die Grenze des Vibe Coding.
Das Problem ist nicht mehr, ob AI Code schreiben kann. Das kann sie.
Das Problem ist, wie viele Entscheidungen wir ihr erlauben, jedes Mal erneut zu treffen, wenn sie das System verändert.
„Plan with the best model, execute with a cheaper one“ reicht nicht aus
Eine populäre Strategie für die Arbeit mit Modellen klingt vernünftig:
Plan with the best model. Execute with a cheaper model.
Das leistungsstarke Modell entwirft. Das günstigere implementiert.
Zwischen diesen beiden Schritten muss jedoch mehr liegen als ein Plan in Markdown.
Wenn wir dem zweiten Modell ein Dokument mit einem Dutzend Entscheidungen geben, muss es immer noch herausfinden, welche davon Anforderungen sind, welche nur Vorschläge, wie sie sich auf die bestehende Codebase beziehen und wo sein eigener Entscheidungsspielraum endet.
Formal hat es einen Plan erhalten.
Praktisch erledigt es weiterhin einen Teil der Architekturarbeit.
Deshalb ist es hilfreich, drei Arten von Aufgaben zu unterscheiden, die wir normalerweise einfach unter „Coding“ zusammenfassen.
Ein Decision Problem liegt vor, wenn entschieden werden muss, wie das System funktionieren soll.
Ein Reasoning Problem entsteht, wenn eine Lösung existiert, ihr Auffinden aber die Analyse von Abhängigkeiten, Alternativen oder Fehlern erfordert.
Ein Execution Problem beginnt dort, wo die Entscheidung bereits getroffen wurde und ihre Konsequenzen korrekt umgesetzt werden müssen.
Alle drei können in einem Pull Request enden.
Aber nicht alle benötigen dieselbe Intelligenz.
Ein besseres Modell und ein höheres Reasoning Level lösen unterschiedliche Probleme
Hier lohnt es sich, zwei Achsen voneinander zu trennen.
Die eine ist die Capability des Modells.
Die andere ist der Reasoning Effort – also wie viel Arbeit wir einem bestimmten Modell für ein Problem erlauben.
Ein größeres Reasoning Budget kann einem Modell helfen, mehr Varianten zu prüfen, Hypothesen zu testen oder die eigene Lösung zu verifizieren. Daraus folgt jedoch keine allgemeine Regel, nach der ein schwächeres Modell auf max einem stärkeren Modell auf medium entspricht.
Das lässt sich gut an aktuellen OpenAI-Evals beobachten.
Auf SWE-Bench Pro erreicht GPT-5.6 Sol 64,6 %, Luna 62,7 %. Das ist nur ein kleiner Unterschied. Auf SEC-Bench Pro sind es dagegen 71,2 % gegenüber 48,9 %. Beim internen Research Debugging 68,3 % gegenüber 50,8 %.
GPT-6 Astra zeigt denselben Effekt aus einer anderen Perspektive: Auf Terminal-Bench 4.0 erreicht es 57,9 %, während GPT-5.6 Sol bei 37,3 % liegt.
Daraus ergibt sich keine einfache Hierarchie des „besten Modells fürs Coding“.
Es ergibt sich etwas Nützlicheres:
Der Vorteil eines stärkeren Modells hängt von der Klasse des Problems ab, das wir ihm geben.
Wenn die Entscheidungen bereits getroffen wurden und die Aufgabe stark begrenzt ist, kann ein günstigeres Modell völlig ausreichen.
Wenn es gleichzeitig die Domäne verstehen, versteckte Annahmen aufdecken, die Architektur entwerfen und Nebenwirkungen vorhersehen muss, kaufen wir Capability.
Deshalb sollte Frontier Intelligence vor allem dort eingesetzt werden, wo noch Unsicherheit besteht.
Die teuerste Entscheidung ist die, die wir ein zweites Mal treffen
Nehmen wir an, eine Anwendung besitzt Seiten, Dokumentation und einen Blog.
Jeder dieser Typen soll einen Titel, einen Slug, eine Sprache, eine SEO-Beschreibung, Inhalt, einen Owner sowie die Möglichkeit besitzen, zu einem bestimmten Zeitpunkt veröffentlicht zu werden. Der Slug soll innerhalb einer Sprache eindeutig sein.
Wir können diese Annahmen separat in mehreren Implementierungen kodieren.
Oder wir schreiben sie einmal auf.
Im tatsächlichen GOAT-Modell definiert die Basiseinheit content unter anderem title, slug, lang, publication_date, description, body, die Relation owner sowie den Constraint unique(lang, slug).
page, doc und blog erweitern diese Basis um ihre eigene SSR-, SEO- und CRUD-Konfiguration.
Im klassischen Software Engineering ist das einfach eine sinnvolle Abstraktion.
In einer Umgebung, in der auch AI Agents die Codebase verändern, entsteht jedoch ein zusätzlicher Effekt.
Der nächste Agent muss die gemeinsamen Regeln nicht erneut aus drei ähnlichen Implementierungen rekonstruieren.
Die Entscheidung wurde in eine einzige Repräsentation komprimiert.
Für diesen Text nennen wir das Decision Compression:
Eine Domänenentscheidung wird in einer Form festgehalten, sodass spätere Schritte des Prozesses sie nicht erneut interpretieren müssen.
Das kann ein Schema, ein Typ, eine DSL, ein API Contract, eine Policy oder ein Constraint sein.
Nicht jedes dieser Werkzeuge ist ein gleich starker Vertrag.
Aber die Richtung ist wichtiger als die konkrete Technologie.
Dokumentation sagt dem Agenten, was wir tun wollten. Ein Vertrag sollte begrenzen, was er tun darf
Heutige agentische Systeme werden mit immer mehr Kontext umgeben.
Wir haben AGENTS.md, Architecture Docs, System Prompts, Style Guides und Codebeispiele.
Das hilft.
Aber es gibt weiterhin einen grundlegenden Unterschied zwischen dem Satz:
Ein Slug sollte innerhalb einer Sprache eindeutig sein
und der Deklaration:
unique(lang, slug)
Den ersten muss der Agent interpretieren.
Die zweite kann das System prüfen.
Das ist keine neue Idee. Software Engineering nutzt seit Langem DSLs, Schemas, Type Systems, Model-Driven Development und Generatoren.
Neu ist die Umgebung, in der ein solches formales Modell gleichzeitig zu einer Schnittstelle zwischen Mensch, LLM und Generator werden kann.
Unmesh Joshi beschrieb 2026 in *DSLs Enable Reliable Use of LLMs* ein sehr ähnliches Muster. Sein Argument ist praktisch: Eine kleine, begrenzte DSL reduziert die Anzahl möglicher Repräsentationen derselben Intention, während Parser, Type Checker oder Compiler dem Agenten deterministisches Feedback liefern können.
Das ist wesentlich interessanter als einfach nur ein „besserer Prompt“.
Ein Prompt hilft dem Agenten, richtig zu raten.
Ein Vertrag sollte dafür sorgen, dass ein Teil der falschen Antworten gar nicht mehr zulässig ist.
Contract-Driven AI Development existiert bereits – und das sollte man offen sagen
Der Begriff selbst ist nicht unsere Erfindung.
Enrico Piovesana veröffentlichte im November 2025 das Framework Contract-Driven AI Development (C-DAD). Sein Ausgangspunkt ist sehr ähnlich: Die meisten Codebases speichern Intention und Einschränkungen implizit, sodass ein Agent gezwungen ist, sie zu rekonstruieren. C-DAD schlägt maschinenverifizierbare Verträge vor, die unter anderem Preconditions, Postconditions und Invariants enthalten.
Mich interessiert hier eine verwandte, aber stärker generator-first ausgerichtete Variante dieser Idee.
Nicht nur:
Wie sorgen wir dafür, dass der Agent den Vertrag versteht?
Sondern auch:
Wie viele Konsequenzen dieses Vertrags können wir ausführen, ohne überhaupt ein Modell zu verwenden?
GOAT ist gerade deshalb ein gutes Case Study, weil es ein deklaratives Modell mit der Generierung weiterer Anwendungsschichten verbindet.
Zurück zur Lizenz
Unsere Business-Anforderung lautet:
Nach der Bezahlung eines Produkts vom Typ
digital_licensesoll der Nutzer eine Lizenz für 365 Tage erhalten, und ein Retry darf kein zweites Entitlement erzeugen.
Der schlechteste mögliche Handoff sieht so aus:
Implementiere Lizenzen im Shop.
Dann ist der Agent gleichzeitig Business Analyst, Architekt, Datenbankdesigner, Backend Developer und Reviewer.
Besser ist es, zuerst das Domänenmodell festzulegen.
Im tatsächlichen GOAT-Modell besitzt ein Produkt ein product_type.
shop_order_item speichert ein eigenes product_type, wodurch der Verhaltenstyp als Snapshot der Transaktion erhalten bleibt.
shop_fulfillment enthält status, product_type, die Anzahl der Versuche, available_at, locked_at und last_error. Ein Domänenkommentar beschreibt diese Entität als langlebige, retrybare Aufgabe, die nach der Zahlung ausgeführt wird.
shop_license speichert das Entitlement des Nutzers sowie seine Relation zu shop_order_item, zusammen mit Status und Gültigkeitszeitraum.
Nach der Architekturentscheidung kann der Ablauf also so aussehen:
business intent
Jahreslizenz nach Zahlung
↓
decision
digital_license ist ein Produktverhalten, das über ein retrybares Fulfillment realisiert wird
↓
contract
product type + order snapshot + fulfillment + license + relations + permissions + constraints
↓
generator
wiederholbare Anwendungsstruktur
↓
cheap model
lokale Fulfillment-Logik + Test
Die wichtigste Veränderung fand statt, bevor die erste Codezeile generiert wurde.
Wir haben den Entscheidungsraum verkleinert.
Ein günstigeres Modell wird dann nützlich, wenn wir von ihm keine Architekturarbeit mehr verlangen
Nach der Festlegung des Vertrags kann die Ausführungsaufgabe deutlich enger formuliert werden:
Implementiere den
digital_license-Handler gemäß dem bestehenden Modell. Ändere weder Schema noch API. Erzeuge für die relevanten Order Items das Entitlement, setze die Gültigkeitsdaten, bewahre Retryability und füge einen Test hinzu.
Das Modell muss nicht mehr darüber nachdenken:
wo die Lizenz gespeichert wird,
wie Fulfillment repräsentiert wird,
ob wir eine neue Entität benötigen,
wie das Entitlement mit der Bestellung verknüpft wird.
Diese Entscheidungen wurden bereits getroffen.
Übrig bleibt ein begrenztes Implementierungsproblem.
Das ist wichtiger als der reine Vergleich von Modellpreisen.
Wir versuchen nicht, Astra durch Luna zu ersetzen.
Wir versuchen, das Problem so zu verändern, dass es Astra gar nicht mehr benötigt.
Der Generator sollte alles übernehmen, was wir nicht erneut verhandeln wollen
LLMs und Generatoren haben gegensätzliche Stärken.
Ein Sprachmodell ist gut im Umgang mit Unsicherheit. Es kann unvollständige Anforderungen analysieren, Optionen vergleichen und eine Lösung anpassen.
Ein Generator sollte langweilig sein.
Wenn wir ein einziges DTO-Muster festgelegt haben, wollen wir nicht für jede Entität eine neue Interpretation.
Wenn jedes Feld eines bestimmten Typs gleich funktionieren soll, ist Kreativität hier eine Quelle von Drift.
Deshalb lautet eine der wichtigsten Regeln dieses Ansatzes:
Use AI to decide what. Use generators to repeat how.
In GOAT gibt es noch eine interessante zweite Ebene: AI kann dabei helfen, die Templates des Generators selbst zu erstellen.
Das verändert die Größenordnung des Nutzens.
Wenn ein starkes Modell ein einzelnes Feature implementiert, nutzen wir sein Reasoning einmal.
Wenn es uns hilft, ein wiederholbares Muster zu erkennen und in den Generator zu verschieben, kann dieselbe Entscheidung in Dutzenden zukünftigen Implementierungen wiederverwendet werden.
Genau hier beginnt AI nicht nur beim Schreiben des Systems zu helfen, sondern auch bei der Verbesserung der Maschine, die dieses System produziert.
Ein Vertrag ist aber nur so viel wert, wie er tatsächlich erzwingt
Hier liefert das eigene GOAT-Modell ein sehr gutes Gegenbeispiel.
product_type, das ausführbares Produktverhalten steuern kann, ist derzeit short_text.
Aus Sicht des Schemas sind daher all diese Werte gleichermaßen gültig:
digital_license
digital-licence
license365
Wenn die Menge möglicher Verhaltensweisen endlich ist, wäre ein Enum oder ein explizites Handler Registry ein stärkerer Vertrag.
Ein noch interessanteres Beispiel findet sich in shop_fulfillment.
Der Kommentar beschreibt die Eindeutigkeit des Order/Type-Paars als Mechanismus zur Sicherstellung der Idempotenz.
Im gezeigten Modell ist jedoch kein Constraint sichtbar, der diese Eindeutigkeit tatsächlich erzwingt.
Das ist kein Makel, den man verstecken sollte.
Es zeigt exakt die Grenze zwischen Intention und Vertrag.
Ein Kommentar kann dem Agenten sagen, dass eine Operation idempotent sein soll.
Ein Constraint kann dafür sorgen, dass das System einen Zustand ablehnt, der diese Regel verletzt.
Und genau deshalb reicht es nicht aus, einfach nur eine DSL zu besitzen.
Contract-Driven Development beginnt dort, wo wichtige Invariants nicht nur beschrieben, sondern tatsächlich durchgesetzt werden können.
Nicht alles sollte in die DSL wandern
Es gibt auch das entgegengesetzte Risiko.
Zuerst besitzt die DSL ein paar einfache Deklarationen.
Dann brauchen wir Ausnahmen.
Wir fügen Bedingungen hinzu.
Hooks.
before.
after.
retry.
unless.
custom_handler.
Irgendwann stellen wir fest, dass wir eine Programmiersprache gebaut haben – nur eine schlechtere.
Joshi weist genau auf diese Spannung hin: Eine DSL hilft einem LLM dann, wenn sie begrenzt bleibt und klare Grenzen definiert.
Deshalb ist die praktische Regel einfach:
Formalisiere, was sich wiederholt. Programmiere, was außergewöhnlich ist.
Daten, Relationen, Constraints, Standard-Permissions oder CRUDs sind gute Kandidaten für Formalisierung.
Ungewöhnliche Algorithmen und einmalige Verhaltensweisen gehören oft weiterhin in normalen Code.
Die Grenze wird sich mit der Reife des Systems verschieben.
Und das ist gut so.
Das größte Problem von AI Drift muss nichts mit Halluzinationen zu tun haben
Stellen wir uns eine andere Anforderung vor:
Ein Nutzer kann sein Profil bearbeiten.
Die Implementierung sieht gut aus.
Später kommt eine Präzisierung:
Aber er darf seine E-Mail-Adresse nicht ändern.
Security ergänzt eine weitere Regel:
Eine Änderung der E-Mail-Adresse muss einen separaten Verifizierungsprozess durchlaufen.
Das Admin Panel verwendet weiterhin das alte CRUD.
Eine API nutzt das neue Permission-Modell, eine andere das alte.
Der Agent muss nichts erfinden, um einen Fehler zu machen.
Es reicht, wenn er einen Teil des Problems korrekt löst.
Mit wachsender Codebase wächst auch die Anzahl der Stellen, aus denen Intention rekonstruiert werden muss.
Ein größeres Context Window hilft dabei, mehr Code zu lesen.
Es garantiert jedoch nicht, dass der Agent eine Business-Entscheidung von einem zufälligen Implementierungsdetail unterscheiden kann.
Deshalb wird ein wichtiger Teil der Skalierung von AI Coding nicht ausschließlich darin bestehen, dass Modelle mehr Kontext aufnehmen können.
Es wird auch darum gehen, dass Organisationen die Menge an Kontext reduzieren, der überhaupt interpretiert werden muss.
DECIDE → FREEZE → EXPAND → VERIFY
Das gesamte Modell lässt sich auf vier Phasen reduzieren.
DECIDE – ein starkes Modell oder ein Mensch arbeitet an dem, was wir noch nicht wissen: Domäne, Architektur, Security, Migration, schwieriger Bug, Business-Konsequenzen.
FREEZE – sobald eine Entscheidung stabil genug ist, existiert sie nicht mehr nur in einer Unterhaltung. Sie wandert in ein Schema, ein Domänenmodell, eine DSL, einen API Contract, eine Policy, einen Test oder eine Generatorregel.
EXPAND – der Generator führt die mechanischen Konsequenzen aus. Ein günstigeres Modell füllt kleine, klar begrenzte Lücken.
VERIFY – Parser, Compiler, Schema, Tests, Static Analysis und Review prüfen das Ergebnis. Ein Modell kann an dieser Schleife beteiligt sein, sollte aber nicht der einzige Richter über seine eigene Arbeit sein.
Dieser Ansatz entfernt AI nicht aus der Implementierung.
Er verändert den Ort, an dem wir ihre Intelligenz einsetzen.
Die interessanteste Form von Unternehmensgedächtnis könnte Code sein, der nicht mehr interpretiert werden muss
Organisationen besitzen viel mehr technisches Wissen, als in ihrer Dokumentation steht.
Wie Ownership funktioniert.
Welche Daten als Snapshot gespeichert werden.
Welche Rollen Daten verändern dürfen.
Was ein Bestellstatus bedeutet.
Wie ein korrektes CRUD aussieht.
Welche Verhaltensweisen idempotent sein müssen.
Dieses Wissen lebt in Code, Pull Requests, Tickets, Dokumentation und in den Köpfen der Menschen.
Ein LLM kann versuchen, es zu rekonstruieren.
Aber Wissen bei jeder Änderung erneut zu rekonstruieren ist teuer.
Wenn sich ein Teil dieser Entscheidungen in einen Constraint, ein Schema oder einen Generator überführen lässt, sind sie nicht mehr ausschließlich Wissen des Teams.
Sie werden zu Eigenschaften des Systems.
Und genau deshalb lohnt es sich, Generatoren nicht nur als Mittel zum schnelleren Schreiben von Boilerplate zu betrachten.
Sie können auch ein Werkzeug sein, um Entscheidungen der Organisation in einer Form festzuhalten, die zukünftige Modelle automatisch erben.
Was kommt nach dem Vibe Coding?
Vibe Coding beantwortet die Frage:
Kann AI das bauen?
Immer häufiger lautet die Antwort: ja.
In einem großen System ist jedoch eine andere Frage interessanter:
Muss der nächste Agent in sechs Monaten erneut herausfinden, warum wir es genau so gebaut haben?
Wenn ja, bezahlen wir jedes Mal erneut für dieselbe Entscheidung.
Modelle werden besser.
Reasoning wird günstiger.
Agents werden länger arbeiten.
Context Windows werden größer.
Aber ein Agent, der eine Million Codezeilen liest, muss trotzdem herausfinden, welche davon Intention repräsentieren und welche nur zufällige Implementierungsgeschichte sind.
Contract-Driven AI Development schlägt eine andere Richtung vor.
Nicht zu versuchen, AI immer besser darin zu machen, unser System zu erraten.
Sondern das System so zu gestalten, dass AI immer weniger raten muss.
Ein starkes Modell sollte dabei helfen, Entscheidungen dort zu treffen, wo Unsicherheit besteht.
Ein Vertrag sollte die Entscheidungen festhalten, die wir nicht erneut verhandeln wollen.
Ein Generator sollte ausführen, was wir bereits wissen.
Und ein günstigeres Modell sollte ein begrenztes Problem erhalten, bei dem wir tatsächlich noch Flexibilität benötigen.
Die teuerste Intelligenz sollte nicht dort eingesetzt werden, wo am meisten Code entsteht.
Sie sollte dort eingesetzt werden, wo Entscheidungen entstehen, die später tausendfach wiederholt werden.